##
#   Project: gmediacatalog - Catalog your media to find them later
#    Author: Fabio Castelli <muflone@vbsimple.net>
# Copyright: 2010 Fabio Castelli
#   License: GPL-2+
#  This program is free software; you can redistribute it and/or modify it
#  under the terms of the GNU General Public License as published by the Free
#  Software Foundation; either version 2 of the License, or (at your option)
#  any later version.
# 
#  This program is distributed in the hope that it will be useful, but WITHOUT
#  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
#  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
#  more details.
# 
# On Debian GNU/Linux systems, the full text of the GNU General Public License
# can be found in the file /usr/share/common-licenses/GPL-2.
##

import time
import gc

import gtk
import gobject
import gio

import plugins
from macros import *
from giodevices import GIODevices

u = unicode


class ScanFolders(object):
  def __init__(self, connection):
    self.connection = connection
    self.errors = []
    self.skip_gvfs = False
    self.__cancelScan = False
    self.scanningPath = ''
    self.devices = GIODevices()

  def __del__(self):
    print 'destroy'

  def cancel_scan(self):
    "Cancel current running scan"
    self.__cancelScan = True
    self.scanningPath = ''

  def garbage_collect(self):
    "Garbage collect to save memory"
    gc.collect()
    return True

  def scan_volume(self, name, description, uri, category_id, folder_id):
    "Scan a volume and its subfolders"
    timeout = gobject.timeout_add(3000, self.garbage_collect)

    self.__cancelScan = False
    # Insert new volume
    volume_id = self.connection.add_volume(
      name, description, uri, category_id, 
      GIODevices().find_name_by_uri(uri)[:-1],
      folder_id
    )
    self.errors = []
    # Scan volume
    self.scan_folder(gio.File(uri), volume_id, category_id)
    # Commit database changes
    self.connection.commit()
    return volume_id

  def scan_folder(self, folder, volume_id, category_id):
    "Scan a folder for files"
    plugins.signal_proxy('on_before_new_path')
    self.scanningPath = folder.get_uri().replace('%20', ' ')
    # Folder callback to update UI
    gtk_process_events()
    plugins.signal_proxy('on_new_path', argc=2, args=(volume_id, folder))
    # Insert new folder
    folder_id = self.connection.add_path(
      volume_id, folder.get_uri().replace('%20', ' '), ''
    )
    # Skip gvfs
    info = folder.query_info('standard::name')
    if info.get_name() == '.gvfs' and self.skip_gvfs:
      print 'skipping gvfs'
      return
    # Loop for files and subfolders
    for info in folder.enumerate_children('*'):
      plugins.signal_proxy('on_before_new_file')
      child = folder.get_child(info.get_name())
      # Insert new file/folder
      symlink = info.get_attribute_byte_string('standard::symlink-target')
      if symlink is None:
        symlink = ''
      plugins.signal_proxy('on_new_file', argc=5, 
        args=(volume_id, folder_id, child, info, category_id))
      file_id = self.connection.add_file(
        volume_id,                                    # Volume ID FK
        folder_id,                                    # Path ID FK
        u(info.get_name()),                           # File name
        info.get_size(),                              # Size
        info.get_file_type(),                         # File Type
        u(info.get_content_type()),                   # Content type
        u(';'.join(info.get_icon().get_names())),     # Icons list
        info.get_modification_time(),                 # Modification time
        info.get_attribute_uint64('time::access'),    # Access time
        info.get_attribute_uint64('time::changed'),   # Changed time
        u(info.get_attribute_string('owner::user')),  # User owner
        u(info.get_attribute_string('owner::group')), # User group
        info.get_attribute_uint32('unix::mode'),      # Mode
        u(symlink),                                   # Target
        info.get_is_hidden() and 1 or 0,              # Flags (hidden)
        '',                                           # Description
        category_id,                                  # Category ID FK
        0                                             # Extra info
      )
      plugins.signal_proxy('on_after_new_file', argc=1, args=file_id)
      # Cancel running scan
      if self.__cancelScan:
        print 'cancel'
        break
      if (info.get_file_type() == gio.FILE_TYPE_DIRECTORY) and \
        (not info.get_is_symlink()):
        try:
          # Scan subfolders
          self.scan_folder(child, volume_id, category_id)
        except gio.Error, error:
          print child.get_uri(), error
          self.errors.append((child.get_uri(), error))
          #raise error
      child = None
      info = None
    folder = None
    plugins.signal_proxy('on_after_new_path', argc=1, args=folder_id)
